<?php
/**
 * 公共函数库
 *
 * @author virowin<virowin@gmail.com>
 * @version $1.0
 */

/**
 * 逻辑错误退出
 *
 * @param int $error_code
 * @param string $error_msg
 * @param string $app_name
 * @param string $refer
 * @param int $output_type 1:json 2:xml
 */
function ErrorExit($errorCode,$errorMsg,$added_info=array(),$app_name='',$refer='',$result_format=''){
	//$CFG['app_name'],get_page_refer(),$clean_gp['result_format']
	if (!$app_name) {
		global $CFG;
		$app_name = $CFG['app_name'];
	}
	if (!$refer) {
		$refer = get_page_refer();
	}
	if (!$result_format) {
		global $clean_gp;
		$result_format = $clean_gp['result_format'];
	}
	
	switch (strval($app_name)){
		//api错误退出
		case 'wine':
		case 'pk':
		case 'apict/baobao' : {
			$Template = array('errorCode'=>intval($errorCode),'errorMsg'=>strval(strip_tags($errorMsg)),'timestamp'=>time());
			if (is_array($added_info) && count($added_info)) {
				$Template = $Template + $added_info;
			}
			switch (intval($result_format)){
				case 2 : echo Lib_XMLUtil::array_to_xml($Template); break;
				case 1 :
				default: echo json_encode($Template); break;
			}
			break;
		}
		
		//comment错误退出
		case 'comment' : {
			$Template = array('errorCode'=>intval($errorCode),'errorMsg'=>strval(strip_tags($errorMsg)));
			if (is_array($added_info) && count($added_info)) {
				$Template = $Template + $added_info;
			}
			switch (intval($result_format)){
				case 3 : echo serialize($Template); break;
				case 2 : echo Lib_XMLUtil::array_to_xml($Template); break;
				case 1 :
				default: echo json_encode($Template); break;
			}
			break;
		}
		
		default: 
			echo 'error get $app_name';
			break;
	}
	exit;
}
function error($code,$msg){
    global $CFG;
    if($CFG['display_errors'] == 1){
        echo "error->".$code.":".$msg."\n\r";
        exit();
    }else{
        exit("404 you know de");
    }
}
function alert($object,$url = null,$notSendHeader = false){
    $notSendHeader===false && header("Content-type: text/html; charset=utf-8");
    echo "<script>alert('$object');</script>";
    if($url == -1){
        print("<script>window.history.go(-1);</script>");
    }else {
        $url!= null && print("<script>window.location=\"".$url."\";</script>");
    }
    exit();
}
function dump($list){
    echo "<pre>";
    var_dump($list);
    echo "</pre>";
    exit();
}
function print_z($list){
    echo "<pre>";
    print_r($list);
    echo "</pre>";
    exit();
}
/**
 * $_SERVER['HTTP_REFERER']
 *
 * @return unknown
 */
function get_page_refer(){
	return $_SERVER['HTTP_REFERER'];
}
/**
 * 获取本页的URL地址
 *
 * @param bool $absolute 是否取全地址
 * @access public
 * @return string
 */
function get_page_url( $absolute = true ) {
	$host = $_SERVER['HTTP_HOST'];
	$host = str_replace( ':8000', '', $host );
	$port = ( $_SERVER['SERVER_PORT'] == 8000 || $_SERVER['SERVER_PORT'] == 80 || $_SERVER['SERVER_PORT'] == 443 ) ? '' : ":{$_SERVER['SERVER_PORT']}";
	$uri = $_SERVER['REQUEST_URI'];
	$protocal = $_SERVER['SERVER_PORT'] == 443 ? 'https://' : 'http://';
	return $absolute ? $protocal . $host . $port . $uri : $uri;
}

/**
 * 转换编码，m.dd通常是转换为utf-8
 *
 * @param string $string  要转换的字符串
 * @param string $toencode 要转换为的编码,默认为UTF-8
 * @return string
 */
function convert_encoding( $string, $to_encode = 'UTF-8' ){
	//当前编码
	$now_encode = detect_encode( $string );
	// 只有编码不同时才转换
	if( strtolower( $to_encode ) != strtolower( $now_encode ) ){
		$string = mb_convert_encoding( $string, $to_encode, $now_encode );
	}
	return $string;
}
function auto_convert( &$string ){
	$string = convert_encoding( $string );
}
/**
 * 检测字符串当前编码
 *
 * @param string $string 需要检测的字符串
 * @access public
 * @return string 字符编码:UTF-8,...
 */
function detect_encode( $string ){
	$encodes = array( 'ASCII', 'UTF-8', 'GBK', 'GB2312', 'CP936' );
	$now_encode = mb_detect_encoding( $string, $encodes);
	if (false===$now_encode) {	//user reco 为什么返回的东西就不能分析出编码呢...
		return 'CP936';
	}
	return $now_encode;
}

/**
 * 转换gbk=>utf-8
 *
 * @param unknown_type $string
 */
function auto_convert_gbk_to_utf8( &$string ){
	$string = mb_convert_encoding( $string, 'UTF-8', 'GBK' );
}
/**
 * 格式化00.00 原实现方法有bug...so改成sprintf的
 */
function convert_float_with_2decimals($float_char) {
	return sprintf("%.02f",floatval($float_char));
}
/**
 * 计算时间段 原名date_diff 与php5.3冲突...so 改名date_diff_dd
 * @param <type> $start
 * @param <type> $end
 * @return <type>
 */
function date_diff_dd($start, $end="") {
	$sdate = strtotime($start);
	if ($end == '') {
		$end = date("Y-m-d H:i:s", time());
	}
	$edate = strtotime($end);
	if ($start > $end) {
		return false;
	}
	$time = $edate - $sdate;
	if($time>=0 && $time<=59) {
		// Seconds
//		$timeshift = $time.'秒';
	} elseif($time>=60 && $time<=3599) {
		// Minutes + Seconds
		$pmin = ($edate - $sdate) / 60;
		$premin = explode('.', $pmin);
		$presec = $pmin-$premin[0];
		$sec = $presec*60;
//		$timeshift = $premin[0].'分'.round($sec,0).'秒';
		$timeshift = $premin[0].'分';
	} elseif($time>=3600 && $time<=86399) {
		// Hours + Minutes
		$phour = ($edate - $sdate) / 3600;
		$prehour = explode('.',$phour);
		$premin = $phour-$prehour[0];
		$min = explode('.',$premin*60);
		$presec = '0.'.$min[1];
		$sec = $presec*60;
//		$timeshift = $prehour[0].'小时'.$min[0].'分'.round($sec,0).'秒';
		$timeshift = $prehour[0].'小时'.$min[0].'分';
	} elseif($time>=86400) {
		// Days + Hours + Minutes
		$pday = ($edate - $sdate) / 86400;
		$preday = explode('.',$pday);
		$phour = $pday-$preday[0];
		$prehour = explode('.',$phour*24);
		$premin = ($phour*24)-$prehour[0];
		$min = explode('.',$premin*60);
		$presec = '0.'.$min[1];
		$sec = $presec*60;
//		$timeshift = $preday[0].'天'.$prehour[0].'小时'.$min[0].'分'.round($sec,0).'秒';
		$timeshift = $preday[0].'天'.$prehour[0].'小时'.$min[0].'分';
	}
	return $timeshift;
}
/**
 * Enter description here...
 *
 * @param unknown_type $datetime
 * @return unknown
 */
function convert_datetime_str_to_array ($datetime) {
	$temp = explode(" ", $datetime);
	$date_array = explode('-', $temp[0]);
	$time_array = explode(':', $temp[1]);
	$date_time_array['Y'] = $date_array[0];
	$date_time_array['m'] = $date_array[1];
	$date_time_array['d'] = $date_array[2];
	$date_time_array['H'] = $time_array[0];
	$date_time_array['i'] = $time_array[1];
	$date_time_array['s'] = $time_array[2];
	return $date_time_array;
}
/**
 * 转换XML文件编码，主要针对GBK[2312]或者GBK编码的进行处理, 同时去掉可能影响XML解析错误的字符
 * 
 * @param string $xml_string 要转换的字符串
 * @param string $encode 要转换为的编码,默认为UTF-8
 * @access public
 * @return string
 */
function convert_xml_encode( $xml_string, $encode = 'UTF-8' ){
	$now_encode = detect_encode( $xml_string );
	$xml_string = preg_replace( "/(^<\?xml.*?encoding.*?)GB2312|GBK(.*?\?>)/i" ,'${1}' . $encode . '${2}' , trim( $xml_string ) ); //如果头部声明是GB2312则替换为$encode
	$xml_string = iconv( $now_encode, 'UTF-8//IGNORE', $xml_string );
	return $xml_string;
}



/**
 * 过滤URL string中的元素
 *
 * @param string $url 请求的URL地址
 * @access public
 * @return string 响应字符串
 */
function set_default_value( $input_array, $default_values ) {
	foreach ( $default_values as $key => $value ) {
		if( !isset( $input_array[$key] ) || (empty( $input_array[$key] ) && $input_array[$key] != 0) ) {
			$input_array[$key] = $value;
		}
	}
	return $input_array;
}

function array_pick_bykey($array, $key_name) {
	return $array[$key_name];
}
/**
 * 判断是否为搜索引擎  
 * 
 * @access public
 * @return bool
 */
function is_robot(){
	$ua = $_SERVER['HTTP_USER_AGENT'];
	$kw_spider = 'Bot|Crawl|Spider|slurp|sohu-search|lycos|robozilla|mobier|heritrix';
	if( preg_match( "/($kw_spider)/i", $ua ) ){
		return true;
	}else{
		return false;
	}
}
/**
 * 封禁IP 
 * 
 * @param mixed $to_url 
 * @access public
 * @return void
 */
function ban_ip( $to_url = null ){
	global $MDD;
	$ban_ips = $MDD['ban_ips'];
	$ip = get_real_ip();	
	$check_result = false;
	// 检查IPlist
	if( in_array( $ip, $ban_ips['iplist'] ) ){
		$check_result = true;
	}else{
		// 检查IP段
		$pos = strrpos( $ip, '.' );
		$ip_section = substr( $ip, 0, $pos );
		if( in_array( $ip_section, $ban_ips['section'] ) ){
			$check_result = true;
		}
	}
	// 结果处理
	if( true == $check_result ) {
		if( null == $to_url ){
			$to_url = '/';
		}
		header( 'Location: ' . $to_url );
		exit;
	}
}

function redirect_url($url){
	if (!headers_sent($filename, $linenum)) {
	    header('Location: '.$url);
	    exit;
	} else {
	    printf("Headers already sent in %s on line %s\n" .
	    	 "Cannot redirect, for now please click this <a " .
	         "href=\"%s\">link</a> instead\n",$filename,$linenum,$url);
	    exit;
	}
}

/**
 * 获取用户IP地址  
 * 
 * @access public
 * @return string
 */
function get_ip(){
	$ip = explode(',',get_real_ip(false));
	$ip = long2ip(ip2long($ip[0]));
	return $ip;
}
function get_real_ip( $need_long = false ){
	if ( isset( $_SERVER ) ){   
		if ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { 
			$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
		} elseif ( isset($_SERVER['HTTP_CLIENT_IP'] ) ) { 
			$ip = $_SERVER['HTTP_CLIENT_IP'];
		} else {
			$ip = $_SERVER['REMOTE_ADDR'];
		}   
	} else {
		if ( getenv( 'HTTP_X_FORWARDED_FOR' ) ) { 
			$ip = getenv( 'HTTP_X_FORWARDED_FOR' );
		} elseif (getenv( 'HTTP_CLIENT_IP' ) ) { 
			$ip = getenv( 'HTTP_CLIENT_IP' );
		} else {
			$ip = getenv( 'REMOTE_ADDR' );
		}   
	}
	if( true == $need_long ){
		$ip = ip2long( $ip );//!!32bit 64bit calculated result not same... so suggest not use it. and use the MySQL function INET_ATON,INET_NTOA with UNSIGNED INT(11) field
	}
	return $ip;
}

/**
 * stdCls to array
 * 一般用于json_decode完,升成的object
 * 
 * @param object $obj
 * @return array
 */
function object_2_array($obj){
	if (is_array($obj) || is_object($obj)) {
		$new_arr = array();
		foreach ($obj as $key => $row){
			$new_arr[$key] = object_2_array($row);
		}
		return $new_arr;
	}else{	//叶子节点
		return $obj;
	}
}

/**
 * 分页
 *
 * @param int $count 总记录数
 * @param int $pagesize 每页条数
 * @param int $page 当前页码
 * @access public
 * @return array array(total => 总记录数, page_count => 总页数, next => 下一页, prev => 上一页, page => 当前页, followup => 以数组形式返回URL string, followup_string => 以字符串型是返回URL string)
 */
function multipage( $count, $pagesize, $page ) {
	$page_count = ceil( $count / $pagesize);
	if( $page > $page_count ) $page = $page_count;
	if( $page < 1 ) $page = 1;
	$multi = array();
	$multi['total'] = (int)$count;
	$multi['page_count'] = (int)$page_count;
	$multi['start'] = (int)(( $page - 1 ) * $pagesize);
	$end = $start + $pagesize;
	$multi['end'] = (int)($end > $multi['total'] ? $multi['total'] : $end);
	if( $page < $page_count ) {
		$multi['next'] = (int)($page + 1);
	}
	if( $page > 1 ) {
		$multi['prev'] = (int)($page - 1);
	}
	$multi['page'] = (int)$page;
	$multi['pagesize'] = (int)$pagesize;
	return $multi;
}
function multipage_followuops( $followups ) {
	$multi = array();
	$multi['followups'] = $followups;
	$multi['followup_string'] = '';
	if( !empty($followups) ) {
		foreach( $followups as $followup ) {
			foreach ( $followup as $key => $value ) {
				$multi['followup_string'] .= '&amp;'.$key.'='.$value;
			}
		}
	}
	return $multi;
}
/**
 * 精简字段
 *
 * @param &$arr
 * @param $allow_keys
 * @return
 */
function reduce_key(&$arr,$allow_keys=array()){
	if (is_array($arr) && is_array($allow_keys)) {
		foreach ($arr as $key => $row){
			if (!in_array($key,$allow_keys)) {
				unset($arr[$key]);
			}
		}
	}
	return ;
}
/**
 * 针对二位数组进行reduce
 *
 * @param &$arr
 * @param $allow_keys
 */
function reduce_key_deep(&$arr,$allow_keys=array()){
	if (is_array($arr)) {
		foreach ($arr as $key => $row){
			reduce_key($arr[$key],$allow_keys);
		}
	}
}

/**
 * 按key做键值
 *
 * @param unknown_type $arr
 * @param unknown_type $key
 */
function arr_index($arr, $key){
	$final_arr = array();
	if (is_array($arr) && count($arr)){
	    foreach ($arr as $row){
	        $final_arr [$row [$key]] = $row;
	    }
	}
	return $final_arr;
}

/**
 * Remove Invisible Characters
 *
 * This prevents sandwiching null characters
 * between ascii characters, like Java\0script.
 *
 * @access      public
 * @param       string
 * @return      string
 */
function remove_invisible_characters($str, $url_encoded = TRUE){
        $non_displayables = array();

        // every control character except newline (dec 10)
        // carriage return (dec 13), and horizontal tab (dec 09)

        if ($url_encoded)
        {
                $non_displayables[] = '/%0[0-8bcef]/';  // url encoded 00-08, 11, 12, 14, 15
                $non_displayables[] = '/%1[0-9a-f]/';   // url encoded 16-31
        }

        $non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S';   // 00-08, 11, 12, 14-31, 127

        do
        {
                $str = preg_replace($non_displayables, '', $str, -1, $count);
        }
        while ($count);

        return $str;
}


/**
 * 分页居中函数
 *
 * @param 总页数 $total_page
 * @param 当前页数 $pageid
 * @param 需要的标签数 $tag
 * @return array 标签列表
 */
function divide_page($total_page, $pageid=1, $tag=10){
    $righttag = intval($tag / 2);
    $lefttag = ceil($tag / 2) - 1;
    if ($pageid - $lefttag <= 0){
        $lefttag = $pageid - 1;
        $righttag = $tag - $pageid;
    }
    if ($total_page - $pageid < $righttag){
        $righttag = $total_page - $pageid;
        $lefttag = $tag - $righttag - 1;
        if ($pageid - $lefttag <= 0)
            $lefttag = $pageid - 1;
    }
    $start = $pageid - $lefttag;
    $buf = array();
    for ($i = $start; $i <= $pageid + $righttag; $i++){
        $buf[] = intval($i);
    }
    return $buf;
}

/**
 * 对于只有限制内外可用的,比如后台...需要调用来检验ip
 * <code>
if(!is_eth0){
	header("Location:index");exit;
}
 * </code>
 *
 * @return unknown
 */
function is_eth0(){
	$net_ip = $_SERVER['SERVER_ADDR'];
	//eth0
	if (substr($net_ip,0,3)=='10.' || substr($net_ip,0,8)=='192.168.' || $net_ip=='127.0.0.1') {
		return true;
	//eth1
	}else{
		return false;
	}
}
function message_send($DestNumber,$Content,$Characterset="utf8")
{
	$result = Lib_APIClient::httpCall("http://cache.in.sohu.com/sms/messagesend.php",
			array("DestNumber"=>$DestNumber,"Content"=>$Content,"Characterset"=>$Characterset),"json");
	return $result;
}
function debug_log($var, $file='log', $dir='debug'){
    global $CFG ;
    $dir = "{$CFG['root_path']}/{$dir}" ;
    if(is_dir($dir) && is_writable($dir)){
        $rs = file_put_contents("{$dir}/{$file}", var_export($var, TRUE)."\n", FILE_APPEND) ;
    }else{
        $rs = FALSE ;
    }
}

//iconv zhangjun
function siconv($in_charset, $out_charset, $var) {
	if(is_array($var)) {
		foreach($var as $key => $val) {
			$var[siconv($in_charset, $out_charset, $key)] = siconv($in_charset, $out_charset, $val);
		}
	} else {
		$var = iconv($in_charset, $out_charset, $var);
	}
	return $var;
}
/**
 * 截取全角和半角混合的字符串以避免乱码
 *
 * @param $str_cut:需要截断的字符串
 * @param $length:允许字符串显示的最大长度
 *
 * @return string
 */
function substr_cut($string, $length, $strpad = '')
{
	$length = ceil($length / 2);
	$_size = mb_strlen($string, 'utf-8');

	if($_size <= $length) return $string;

	$strlen_var = strlen($string);

	// 不包含 html 标签
	/*if(strpos($string, '<') === false)
	 {
	return mb_substr($string, 0, $length);
	}*/

	// 包含截断标志，优先
	if($e = strpos($string, '<!-- break -->'))
	{
		return mb_substr($string, 0, $e);
	}

	// html 代码标记
	$html_tag = 0;

	// 摘要字符串
	$return_string = '';

	/**
	 * 数组用作记录摘要范围内出现的 html 标签
	 * 开始和结束分别保存在 left 和 right 键名下
	 * 如字符串为：<h3><p><b>a</b></h3>，假设 p 未闭合
	 * 数组则为：array('left' => array('h3', 'p', 'b'), 'right' => 'b', 'h3');
	 * 仅补全 html 标签，<? <% 等其它语言标记，会产生不可预知结果
	 */
	$html_array = array('left' => array(), 'right' => array());
	for($i = 0; $i < $strlen_var; ++$i)
	{
		if(!$length)
		{
			break;
		}

		$current_var = substr($string, $i, 1);

		if($current_var == '<')
		{
			// html 代码开始
			$html_tag = 1;
			$html_array_str = '';
		}
		else if($html_tag == 1)
		{
			// 一段 html 代码结束，<>中间如果有单引号或双引号，必须成对出现才算标签闭合
			if($current_var == '>' && (substr_count($html_array_str, '\'') % 2 === 0) && (substr_count($html_array_str, '"') % 2 === 0))
			{
				/**
				 * 去除首尾空格，如 <br /  > < img src="" / > 等可能出现首尾空格
				 */
				$html_array_str = trim($html_array_str);

				/**
				 * 判断最后一个字符是否为 /，若是，则标签已闭合，不记录
				*/
				if(substr($html_array_str, -1) != '/')
				{
						
					// 判断第一个字符是否 /，若是，则放在 right 单元
					$f = substr($html_array_str, 0, 1);
					if($f == '/')
					{
						// 去掉 /
						$html_array['right'][] = str_replace('/', '', $html_array_str);
					}
					else if($f != '?')
					{
						// 判断是否为 ?，若是，则为 PHP 代码，跳过

						/**
						 * 判断是否有半角空格，若有，以空格分割，第一个单元为 html 标签
						 * 如 <h2 class="a"> <p class="a">
						 */
						if(strpos($html_array_str, ' ') !== false)
						{
							// 分割成2个单元，可能有多个空格，如：<h2 class="" id="">
							$html_array['left'][] = strtolower(current(explode(' ', $html_array_str, 2)));
						}
						else
						{
							/**
							 * * 若没有空格，整个字符串为 html 标签，如：<b> <p> 等
							 * 统一转换为小写
							 */
							$html_array['left'][] = strtolower($html_array_str);
						}
					}
				}

				// 字符串重置
				$html_array_str = '';
				$html_tag = 0;
			}
			else
			{
				/**
				 * 将< >之间的字符组成一个字符串
				 * 用于提取 html 标签
				 */
				$html_array_str .= $current_var;
			}
		}
		else
		{
			// 非 html 代码才记数
			--$length;
		}

		$ord_var_c = ord($string{$i});

		switch(true)
		{
			case (($ord_var_c & 0xE0) == 0xC0):
				{// 2 字节
					$return_string .= substr($string, $i, 2);
					$i += 1;
					break;
				}
			case (($ord_var_c & 0xF0) == 0xE0):
				{
					// 3 字节
					$return_string .= substr($string, $i, 3);
					$i += 2;
					break;
				}
			case (($ord_var_c & 0xF8) == 0xF0):
				{
					// 4 字节
					$return_string .= substr($string, $i, 4);
					$i += 3;
					break;
				}
			case (($ord_var_c & 0xFC) == 0xF8):
				{
					// 5 字节
					$return_string .= substr($string, $i, 5);
					$i += 4;
					break;
				}
			case (($ord_var_c & 0xFE) == 0xFC):
				{
					// 6 字节
					$return_string .= substr($string, $i, 6);
					$i += 5;
					break;
				}
			default:
				{
					// 1 字节
					$return_string .= $current_var;
				}
		}
	}

	if($html_array['left'])
	{
		/**
		 * 比对左右 html 标签，不足则补全
		 */

		/**
		 * 交换 left 顺序，补充的顺序应与 html 出现的顺序相反
		 * 如待补全的字符串为：<h2>abc<b>abc<p>abc
		 * 补充顺序应为：</p></b></h2>
		 */
		$html_array['left'] = array_reverse($html_array['left']);

		foreach($html_array['left'] as $index => $tag)
		{
			// 判断该标签是否出现在 right 中
			$key = array_search($tag, $html_array['right']);
			if($key !== false)
			{
				// 出现，从 right 中删除该单元
				unset($html_array['right'][$key]);
			}
			elseif($tag != 'img')
			{
				// 没有出现，需要补全
				$return_string .= '</'.$tag.'>';
			}
		}
	}
	$return_string .= $length > 0 ? '' : $strpad;
	return $return_string;
}//end funtion
